package com.taobao.yugong.common.audit;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.taobao.yugong.common.db.meta.ColumnValue;
import com.taobao.yugong.common.model.position.Position;
import com.taobao.yugong.common.model.record.IncrementOpType;
import com.taobao.yugong.common.model.record.IncrementRecord;
import com.taobao.yugong.common.model.record.Record;

/**
 * 记录一下同步过程中的record数据
 *
 * @author agapple 2013-9-23 下午2:13:46
 */
public class RecordDumper {

    private static final Logger extractorLogger         = LoggerFactory.getLogger("extractor");
    private static final Logger applierLogger           = LoggerFactory.getLogger("applier");
    private static final String SEP                     = SystemUtils.LINE_SEPARATOR;
    private static final String TIMESTAMP_FORMAT        = "yyyy-MM-dd HH:mm:ss:SSS";
    private static String       extractor_format        = null;
    private static String       applier_format          = null;
    private static String       record_format           = null;
    private static int          record_default_capacity = 1024;                                // 预设值StringBuilder，减少扩容影响

    static {
        extractor_format = "* batchId : [{0}] , total : [{1}] , lastPosition [{2}] , Time : {3} " + SEP;
        applier_format = "* batchId : [{0}] , extractorSize : [{1}] , applierSize : [{2}] , ackPosition [{3}] , Time : {4} "
                         + SEP;

        record_format = "-----------------" + SEP;
        record_format += "- Schema: {0} , Table: {1} , Type: {2}" + SEP;
        record_format += "-----------------" + SEP;
        record_format += "---Pks" + SEP;
        record_format += "{3}" + SEP;
        record_format += "---Columns" + SEP;
        record_format += "{4}" + SEP;
        record_format += "---END" + SEP;
    }

    public static void dumpExtractorInfo(Long batchId, List<Record> records, Position lastPosition, boolean dumpDetail) {
        extractorLogger.info(SEP + "****************************************************" + SEP);
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat(TIMESTAMP_FORMAT);
        extractorLogger.info(MessageFormat.format(extractor_format,
            String.valueOf(batchId),
            records.size(),
            ObjectUtils.toString(lastPosition),
            format.format(now)));
        extractorLogger.info("****************************************************" + SEP);
        if (dumpDetail) {// 判断一下是否需要打印详细信息
            extractorLogger.info(dumpRecords(records));
            extractorLogger.info("****************************************************" + SEP);
        }
    }

    public static void dumpApplierInfo(Long batchId, List<Record> extractorRecords, List<Record> applierRecords,
                                       Position position, boolean dumpDetail) {
        applierLogger.info(SEP + "****************************************************" + SEP);
        Date now = new Date();
        SimpleDateFormat format = new SimpleDateFormat(TIMESTAMP_FORMAT);
        applierLogger.info(MessageFormat.format(applier_format,
            String.valueOf(batchId),
            extractorRecords.size(),
            applierRecords.size(),
            ObjectUtils.toString(position),
            format.format(now)));
        applierLogger.info("****************************************************" + SEP);
        if (dumpDetail) {// 判断一下是否需要打印详细信息，目前只打印applier信息，分开打印
            applierLogger.info(dumpRecords(applierRecords));
            applierLogger.info("****************************************************" + SEP);
        }
    }

    public static String dumpRecords(List<Record> records) {
        if (CollectionUtils.isEmpty(records)) {
            return StringUtils.EMPTY;
        }

        // 预先设定容量大小
        StringBuilder builder = new StringBuilder(record_default_capacity * records.size());
        for (Record record : records) {
            builder.append(dumpRecord(record));
        }
        return builder.toString();
    }

    public static String dumpRecord(Record record) {
        IncrementOpType type = IncrementOpType.I;
        if (record instanceof IncrementRecord) {
            type = ((IncrementRecord) record).getOpType();
        }

        return MessageFormat.format(record_format,
            record.getSchemaName(),
            record.getTableName(),
            type,
            dumpRecordColumns(record.getPrimaryKeys()),
            dumpRecordColumns(record.getColumns()));
    }

    public static String dumpRecordColumns(List<ColumnValue> columns) {
        StringBuilder builder = new StringBuilder(record_default_capacity);
        int size = columns.size();
        for (int i = 0; i < size; i++) {
            ColumnValue column = columns.get(i);
            builder.append("\t").append(ObjectUtils.toString(column));
            if (i < columns.size() - 1) {
                builder.append(SEP);
            }
        }
        return builder.toString();
    }

}
